using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;
using System.IO;

namespace PotonCapture
{
    public class ScreenCapture
    {
        public enum TargetRanges
        {
            FullScreen,
            Window,
            Client,
            EnumCount,
        }

        public enum FileTypes
        {
            Bmp,
            Png,
            Jpg
        }

        private TargetRanges _targetRange;

        public TargetRanges TargetRange
        {
            get { return _targetRange; }
            set { _targetRange = value; }
        }

        private FileTypes _fileType;

        public FileTypes FileType
        {
            get { return _fileType; }
            set { _fileType = value; }
        }
	
	
        //private string _folder;

        //public string Folder
        //{
        //    get { return _folder; }
        //    set { _folder = value; }
        //}

        //private int _fileNumber = 1;

        //public int FileNumber
        //{
        //    get { return _fileNumber; }
        //    set { _fileNumber = value; }
        //}

        //private string _baseName = "image";

        //public string BaseName
        //{
        //    get { return _baseName; }
        //    set { _baseName = value; }
        //}
	
        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr GetWindowRect(IntPtr hwnd, out RECT lpRect);

        [DllImport("user32.dll", CharSet = CharSet.Auto,
         CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr GetClientRect(IntPtr hwnd, out RECT lpRect);

        public class Win32Window
        {
            protected IntPtr _handle;

            public IntPtr Handle
            {
                get { return _handle; }
            }

            [StructLayout(LayoutKind.Sequential)]
            protected struct POINT
            {
                public int x;
                public int y;
            }
            [StructLayout(LayoutKind.Sequential)]
            protected struct RECT
            {
                public int left;
                public int top;
                public int right;
                public int bottom;
            }

            [DllImport("user32.dll")]
            protected static extern void ScreenToClient(IntPtr hwnd, ref POINT lpPoint);

            [DllImport("user32.dll")]
            protected static extern void ClientToScreen(IntPtr hwnd, ref POINT lpPoint);

            [DllImport("user32.dll")]
            protected static extern IntPtr GetForegroundWindow();

            [DllImport("user32.dll")]
            protected static extern int GetClientRect(IntPtr hwnd, out RECT lpRect);

            [DllImport("user32.dll")]
            protected static extern int GetWindowRect(IntPtr hwnd, out RECT lpRect);
            
            [DllImport("user32.dll")]
            protected static extern int IsZoomed(IntPtr hwnd);

            public Win32Window(IntPtr handle)
            {
                _handle = handle;
            }

            public static Win32Window GetForegroundWindowApi()
            {
                IntPtr handle = GetForegroundWindow();
                if (handle == IntPtr.Zero)
                {
                    return null;
                }
                Win32Window win = new Win32Window(handle);
                return win;
            }

            public void ScreenToClient(ref Point pt)
            {
                POINT point = new POINT();
                point.x = pt.X;
                point.y = pt.Y;
                ScreenToClient(_handle, ref point);
                pt.X = point.x;
                pt.Y = point.y;
            }

            public void ClientToScreen(ref Point pt)
            {
                POINT point = new POINT();
                point.x = pt.X;
                point.y = pt.Y;
                ClientToScreen(_handle, ref point);
                pt.X = point.x;
                pt.Y = point.y;
            }

            public int GetClientRect(out Rectangle rect)
            {
                RECT rect2;
                int result = GetClientRect(_handle, out rect2);
                rect = new Rectangle();
                rect.X = rect2.left;
                rect.Y = rect2.top;
                rect.Width = rect2.right - rect2.left;
                rect.Height = rect2.bottom - rect2.top;
                return result;
            }

            public int GetWindowRect(out Rectangle rect)
            {
                RECT rect2;
                int result = GetWindowRect(_handle, out rect2);
                rect = new Rectangle();
                rect.X = rect2.left;
                rect.Y = rect2.top;
                rect.Width = rect2.right - rect2.left;
                rect.Height = rect2.bottom - rect2.top;
                return result;
            }

            public bool IsZoomed()
            {
                int result = IsZoomed(_handle);
                return result != 0;
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        public ScreenCapture()
        {
//            _folder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
        }

        //public void CreateFolder()
        //{
        //    if (!Directory.Exists(_folder))
        //    {
        //        Directory.CreateDirectory(_folder);
        //    }
        //}

        //public string GetNextFilePath()
        //{
        //    string path = null;
        //    for (; _fileNumber <= 9999; _fileNumber++)
        //    {
        //        string fileName = String.Format("{0}{1:0000}", _baseName, _fileNumber);
        //        fileName += "." + _fileType.ToString().ToLower();
        //        path = Path.Combine(_folder, fileName);
        //        if (!File.Exists(path))
        //        {
        //            break;
        //        }
        //    }
        //    if (path == null)
        //    {
        //        System.Diagnostics.Debug.Print("capture path create error");
        //        return null;
        //    }
        //    System.Diagnostics.Debug.Print("capture path {0}", path);
        //    return path;
        //}

//        public void ExecuteCapture(out string savePath)
        public void ExecuteCapture(string savePath)
        {
//            savePath = null;
//            CreateFolder();

            Win32Window window = Win32Window.GetForegroundWindowApi();
            if(window == null)
            {
                return;
            }
            IntPtr foreWindow = window.Handle;
            //IntPtr foreWindow = GetForegroundWindow();
            //if (foreWindow == IntPtr.Zero)
            //{
            //    return;
            //}

            //RECT rect2;
            //GetWindowRect(foreWindow, out rect2);
            
            //Rectangle rect = new Rectangle();
            //rect.X = rect2.left;
            //rect.Y = rect2.top;
            //rect.Width = rect2.right - rect2.left;
            //rect.Height = rect2.bottom - rect2.top;

            Rectangle fullScreenRect = Screen.PrimaryScreen.Bounds;

            Rectangle rect = new Rectangle();
            Screen screen = null;
            switch (_targetRange)
            {
                case TargetRanges.FullScreen:
                    screen = Screen.PrimaryScreen;
                    rect = fullScreenRect;
                    break;
                case TargetRanges.Window:
                    window.GetWindowRect(out rect);
                    screen = Screen.FromHandle(foreWindow);
                    break;
                case TargetRanges.Client:
                    window.GetClientRect(out rect);
                    Point pt = new Point();
                    window.ClientToScreen(ref pt);
                    rect.Offset(pt);
                    screen = Screen.FromHandle(foreWindow);
                    break;
            }

            rect.Intersect(fullScreenRect);
            if(_targetRange == TargetRanges.Window && window.IsZoomed())
            {
                rect.Intersect(screen.WorkingArea);
            }
            //rect.Y = Math.Max(rect.Top, 0);
            //rect.X = Math.Max(rect.Left, 0);
            //rect.Width = Math.Min(rect.Right, fullScreenRect.Right) - rect.X;
            //rect.Height = Math.Min(rect.Bottom, fullScreenRect.Bottom - rect.Y);

            if (screen == null || rect.Width <= 0 || rect.Height <= 0)
			{
				return;
			}

//			System.Diagnostics.Debug.Print("capture range x={0}, y={1}, w={2}, h={3}", rect.X, rect.Y, rect.Width, rect.Height);
//			Control target = Control.FromChildHandle(foreWindow);
//			Control target2 = Control.FromHandle(foreWindow);

            //string path = null;
            //for (; _fileNumber <= 9999; _fileNumber++)
            //{
            //    string fileName = String.Format("{0}{1:0000}", _baseName, _fileNumber);
            //    fileName += "." + _fileExt.ToString().ToLower();
            //    path = Path.Combine(_folder, fileName);
            //    if (!File.Exists(path))
            //    {
            //        break;
            //    }
            //}
            //if (path == null)
            //{
            //    System.Diagnostics.Debug.Print("capture path create error");
            //    return;
            //}
            //System.Diagnostics.Debug.Print("capture path {0}", path);

            //string path = GetNextFilePath();
            //if (path == null)
            //{
            //    System.Diagnostics.Debug.Print("capture path create error");
            //    return;
            //}
            string path = savePath;
            System.Diagnostics.Debug.Print("capture path {0}", path);

            ImageFormat format = ImageFormat.Bmp;
            if (_fileType == FileTypes.Png)
            {
                format = ImageFormat.Png;
            }
            else if (_fileType == FileTypes.Jpg)
            {
                format = ImageFormat.Jpeg;
            }

			using (Bitmap bitmap = new Bitmap(screen.Bounds.Width, screen.Bounds.Height, PixelFormat.Format24bppRgb))
            {
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.CopyFromScreen(Point.Empty, Point.Empty, screen.Bounds.Size, CopyPixelOperation.SourceCopy);
                }

				using (Bitmap bitmap2 = new Bitmap(rect.Width, rect.Height, PixelFormat.Format24bppRgb))
				{
					using (Graphics g2 = Graphics.FromImage(bitmap2))
					{
						g2.DrawImage(bitmap, new Rectangle(Point.Empty, rect.Size), rect, GraphicsUnit.Pixel);
					}

					bitmap2.Save(path, format);
				}
			}
//            savePath = path;
			//using (Bitmap bitmap = new Bitmap(rect.Width, rect.Height, PixelFormat.Format24bppRgb))
			//{
			//    using (Graphics g = Graphics.FromImage(bitmap))
			//    {
			//        g.CopyFromScreen(rect.Location, new Point(0, 0), rect.Size, CopyPixelOperation.SourceCopy);
			//    }


			//    bitmap.Save(path, ImageFormat.Bmp);
			//}
        }


    }
}
